package biz.console.controller;

import biz.console.Result;
import biz.console.RedisClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.bind.annotation.*;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * @创建人 xiaojiancheng
 * @时间 2020/7/31
 * @描述 $k$
 */
@RestController
@RequestMapping("/redis")
@Api
public class RedisController {
    @ApiOperation(value = "链接redis",tags = "redis")
    @PostMapping("/connect")
    public Result connect(@RequestBody LoginInfo info) throws Exception {
        RedisClient redisClient_ = new RedisClient(info.host, info.port, info.password);
        String connect = redisClient_.connect();
        return new Result().data(connect);
    }

    @PostMapping("/query")
    @ApiOperation(value = "查询key",tags = "redis")
    public Result queryKeys(@RequestParam String uuid) throws Exception{
        RedisClient client = RedisClient.get(uuid);
        if(client == null){
            return new Result().code(-1).msg("session过期");
        }
        client.beat();

        //  后期优化这个 使用 scan 命令  实现起来有点绕
        Object write = client.write("keys *");
        return new Result().data(write);
    }

    @PostMapping("/detail")
    @ApiOperation(value = "value",tags = "redis")
    public Result detail(@RequestParam String uuid,@RequestParam String key) throws Exception{
        RedisClient client = RedisClient.get(uuid);
        if(client == null){
            return new Result().code(-1).msg("session过期");
        }
        client.beat();

        String keyType = String.valueOf(client.write("type " + key));
        //  如果 string
        if(Objects.equals(keyType,"string")){
            Object write = client.write("get " + key);
            return new Result().data(new KeyDetail("string",write.toString()));
        }

        //  hash
        if(Objects.equals(keyType,"hash")){
            List<Object> list = (List<Object>) client.write("hgetall "+key);
            return new Result().data(new KeyDetail("hash",list));
        }

        return new Result();
    }

    @PostMapping("/delete")
    @ApiOperation(value = "删除",tags = "redis")
    public Result delete(@RequestParam String uuid,@RequestParam String key) throws Exception{
        RedisClient client = RedisClient.get(uuid);
        if(client == null){
            return new Result().code(-1).msg("session过期");
        }
        client.beat();

        String key1 = key.replace(",", " ");
        Object write = client.write("del " + key1);

        return new Result().data(write);
    }

    @PostMapping("/cmd")
    @ApiOperation(value = "命令行",tags = "redis")
    public Result cmd(@RequestBody Cmd cmd)throws Exception{
        RedisClient client = RedisClient.get(cmd.uuid);
        if(client == null){
            return new Result().code(-1).msg("session过期");
        }
        client.beat();

        Object write = client.write(cmd.cmd);
        return new Result().data(write);
    }

//    @RequestMapping(params = {"api=query"})
//    public Mono query(@RequestParam("query") String query, ServerWebExchange exchange) {
//        RedisReactiveCommands redis = getRedis(exchange);
//        return Mono.<List<String>>create(item -> {
//            List<String> rtnList = new LinkedList<>();
//            ScanCursor cursor = ScanCursor.INITIAL;
//            ScanArgs args = new ScanArgs();
//            if (TextUtils.isEmpty(query)) {
//                args.match("*");
//            } else {
//                args.match("*" + query + "*");
//            }
//
//            loop(cursor, args, rtnList, exchange)
//                    .doOnError(error -> {
//                        //  需要抛出错误
//                        item.error(error);
//                    })
//                    .subscribe(rtn -> {
//                        Collections.sort(rtnList);
//                        item.success(rtnList);
//                    });
//        })
//                //  加载key的类型
//                .flatMap(keyList -> {
//                    return Flux.fromIterable(keyList)
//                            .flatMap(str -> {
//                                return redis.type(str)
//                                        .map(value -> {
//                                            ConsoleModel.RedisKeyType redisKeyType = new ConsoleModel.RedisKeyType();
//                                            redisKeyType.setKey(str);
//                                            redisKeyType.setType(String.valueOf(value));
//                                            return redisKeyType;
//                                        });
//                            })
//                            .collectList();
//                })
//                .flatMap(k -> {
//                    return Mono.just(new Result().data(k));
//                });
//    }
//
//    private Mono<List<String>> loop(ScanCursor cursor, ScanArgs args, List<String> keyList, ServerWebExchange exchange) {
//        RedisReactiveCommands redis = getRedis(exchange);
//        return Mono.create(item -> {
//            redis.scan(cursor, args)
//                    .doFinally(seg -> {
//
//                    })
//                    .doOnError(error -> {
//
//                    })
//                    .subscribe(cursor1 -> {
//                        KeyScanCursor cursor2 = (KeyScanCursor) cursor1;
//                        keyList.addAll(cursor2.getKeys());
//                        if (cursor2.isFinished()) {
//                            item.success(keyList);
//                        } else {
//                            //  递归去取key值
//                            loop(cursor2, args, keyList, exchange)
//                                    .subscribe(s -> {
//                                        item.success(keyList);
//                                    });
//                        }
//                    });
//        });
//    }
//
//    @RequestMapping(params = {"api=getByKey"})
//    public Mono getByKey(@RequestParam("key") String key, ServerWebExchange exchange) {
//        RedisReactiveCommands redis = getRedis(exchange);
//        return Mono.create(item -> {
//            redis.type(key)
//                    .subscribe(type -> {
//                        //    string hash list
//                        switch (((String) type)) {
//                            case "string":
//                                redis.get(key)
//                                        .subscribe(rtn -> {
//                                            item.success(new Result<>().data(rtn));
//                                        });
//                                break;
//
//                            case "hash":
//                                // 获取所有的key value
//                                redis.hgetall(key)
//                                        .subscribe(rtn -> {
//                                            item.success(new Result<>().data(rtn));
//                                        });
//                                break;
//
//                            case "list":
//                                // TODO: 2020/7/31
//                                break;
//                        }
//                    });
//        });
//    }
//
//    //  删除一个key 无论是字符串还是hash等
//    @RequestMapping(params = {"api=deleteKey"})
//    public Mono deleteKey(@RequestParam("key") String key, ServerWebExchange exchange) {
//        RedisReactiveCommands redis = getRedis(exchange);
//        return Mono.create(item -> {
//            redis.del(key)
//                    .subscribe(rtn -> {
//                        item.success(new Result<>().data(rtn));
//                    });
//        });
//    }
//
//    //  删除要给hash子项
//    @RequestMapping(params = {"api=getHashItem"})
//    public Mono deleteHashItem(@RequestParam("key") String key, @RequestParam("field") String field, ServerWebExchange exchange) {
//        RedisReactiveCommands redis = getRedis(exchange);
//        return Mono.create(item -> {
//            redis.hdel(key, field)
//                    .subscribe(rtn -> {
//                        item.success(new Result<>().data("success"));
//                    });
//        });
//    }
//
//    //  添加一个hash子项
//    @RequestMapping(params = {"api=addHashKey"})
//    public Mono addHashItem(@RequestParam("key") String key, @RequestParam("field") String field,
//                            @RequestParam("value") String value, ServerWebExchange exchange) {
//        RedisReactiveCommands redis = getRedis(exchange);
//        return Mono.create(item -> {
//            redis.hset(key, field, value)
//                    .subscribe(rnt -> {
//                        item.success(new Result<>().data("success"));
//                    });
//        });
//    }
//
//    //  添加要给字符串
//    @RequestMapping(params = {"api=addStringKey"})
//    public Mono addString(@RequestParam("key") String key, @RequestParam("value") String value, ServerWebExchange exchange) {
//        RedisReactiveCommands redis = getRedis(exchange);
//        return Mono.create(item -> {
//            redis.set(key, value)
//                    .subscribe(rtn -> {
//                        item.success(new Result<>().data(rtn));
//                    });
//        });
//    }
//
//    private RedisReactiveCommands getRedis(ServerWebExchange exchange) {
//        ServerHttpRequest request = exchange.getRequest();
//        String token = request.getQueryParams().getFirst("token");
//
//        ConsoleContext.update(token);
//
//        ConsoleModel.ConnectionCheckInfo connectionCheckInfo = ConsoleContext.get(token);
//        if (connectionCheckInfo == null) {
//            throw new SystemException(426, "会话已经过期");
//        }
//        return ((ConsoleModel.RedisInfo) connectionCheckInfo.getData()).getRedis();
//    }
//
//    private RedisClient_ getRedisClient_(ServerWebExchange exchange) {
//        ServerHttpRequest request = exchange.getRequest();
//        String token = request.getQueryParams().getFirst("token");
//
//        ConsoleContext.update(token);
//
//        ConsoleModel.ConnectionCheckInfo connectionCheckInfo = ConsoleContext.get(token);
//        if (connectionCheckInfo == null) {
//            throw new SystemException(426, "会话已经过期");
//        }
//        return ((ConsoleModel.RedisInfo) connectionCheckInfo.getData()).getRedisClient();
//    }
//
//    @RequestMapping(params = {"api=console"})
//    public Mono console(@RequestBody Map<String, Object> requestMap, ServerWebExchange exchange) {
//        RedisClient_ redisClient_ = getRedisClient_(exchange);
//        return redisClient_.write(String.valueOf(requestMap.get("line")))
//                .map(k -> {
//                    return new Result<>().data(k);
//                });
//    }

    @Setter
    @Getter
    public static class KeyDetail {
        private String type;
        private String value;
        private List<Object> valueList = new LinkedList<>();

        public KeyDetail(String type, String value) {
            this.type = type;
            this.value = value;
        }

        public KeyDetail(String type, List<Object> valueList) {
            this.type = type;
            this.valueList = valueList;
        }
    }

    @Setter
    @Getter
    public static class Cmd {
        private String cmd;
        private String uuid;
    }

    @Setter
    @Getter
    public static class LoginInfo {
        private String host;
        private int port;
        private String password;
    }

}
